package game;

import java.util.*;
public class Game {

	private String oprts[] = { "+", "-", "*", "/", "=" };
	private static String pos0[] = { "A", "B", "C", "D", "E", "F" };
	private static String pos1[] = { "1", "2", "3", "4", "5", "6" };

	// Size of the grid
	public int mGridSize;

	// Random generator
	// public Random mRandom;

	// public ArrayList<Integer> mCandidateCageType;

	// Cages
	public ArrayList<GridCage> mCages;

	// Cells
	public ArrayList<GridCell> mCells;

	// Formulas
	public ArrayList<Formula> mFormulas;

	public Game(int size) {
		this.mGridSize = size;
		this.mCages = new ArrayList<GridCage>();
		this.mFormulas = new ArrayList<Formula>();
		mCells = new ArrayList<GridCell>(size * size);
		for (int j = 0; j < size * size; j++) {
			this.mCells.add(new GridCell());
		}
		for (int i = 0; i < this.mCells.size(); i++) {
			this.mCells.get(i).mRow = i / this.mGridSize;
			this.mCells.get(i).mColumn = i % this.mGridSize;
			this.mCells.get(i).mCellNumber = i;
		}
	}

	public static int getPosition(String pos) {
		int position = -1;
		for (int i = 0; i < 6; i++) {
			if (pos.substring(0, 1).equals(pos0[i])) {
				for (int j = 0; j < 6; j++) {
					if (pos.substring(1).equals(pos1[j])) {
						position = 10 * (i + 1);
						position += j + 1;
						return position;
					}
				}

			}
		}
		return position;

	}

	/**
	 * add cages and formulas 
	 * @param fml
	 * 
	 */
	public void addCage(String[] fml) {

		int cageId = this.mCages.size();

		int result = Integer.parseInt(fml[0]); // check and get the result of
												// formula

		// ArrayList<GridCell> tmp_cells =new ArrayList<GridCell>();
		int operator = 6; // check and get the operator
		for (int i = 0; i < oprts.length; i++) {
			if (fml[1].equals(oprts[i])) {
				operator = i;
			}

		}
		this.mCages.add(new GridCage(cageId, result, operator));
		int numOfCells = Integer.parseInt(fml[2]);

		int position[] = new int[numOfCells]; // check and get cages location
		for (int i = 0; i < numOfCells; i++) {
			int tmp = getPosition(fml[i + 3]);
			position[i] = tmp;
			int cellId = (tmp / 10 - 1) * this.mGridSize + (tmp % 10 - 1);
			this.mCells.get(cellId).setCageId(cageId);
			if (i == 0) {
				if (operator != 4)
					this.mCells.get(cellId).setmCageText(
							Integer.toString(result)
									+ oprts[operator]);
				else
					this.mCells.get(cellId).setmCageText(
							Integer.toString(result));
			}
			this.mCages.get(cageId).addCell(this.mCells.get(cellId));
		}

		this.mFormulas.add(new Formula(result, operator, numOfCells, position));

	}



	public boolean operation(Formula f, int[][] answer) {
		int n = f.getNumOfCells();
		int[] operand = new int[n];

		for (int i = 0; i < n; i++) {
			operand[i] = answer[(f.getPosition()[i] / 10) - 1][(f.getPosition()[i] % 10) - 1];
		}
		Arrays.sort(operand);

		int result = 0;

		switch (f.getOperator()) {
		case 0: // +
			for (int i = n - 1; i >= 0; i--) {
				result += operand[i];
			}
			break;
		case 1: // -
			result = operand[n - 1];
			for (int i = n - 2; i >= 0; i--) {
				result -= operand[i];
			}
			break;
		case 2: // *
			result = 1;
			for (int i = n - 1; i >= 0; i--) {
				result *= operand[i];
			}
			break;
		case 3: // /
			result = operand[n - 1];
			for (int i = n - 2; i >= 0; i--) {
				result /= operand[i];
			}
			break;
		case 4: // =
			result = operand[0];
			break;
		default:
			break;

		}

		if (result != f.getResult())
			return false;

		return true;
	}



public boolean checkAnswer(int[][] answer){
	for (int i = 0; i < this.mFormulas.size(); i++) {
		if (!operation(this.mFormulas.get(i), answer))
			return false;
	}
	System.out.println("Solution Found: " + Arrays.deepToString(answer));
	return true;
	
}
}
